package org.lib.mongodbhello.try1;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.IntStream;

import org.bson.Document;
import org.bson.conversions.Bson;
import org.lib.mongodbhello.try1.entity.User1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.InsertOneResult;
import com.mongodb.client.result.UpdateResult;

import lombok.extern.slf4j.Slf4j;

/**
 * 试验1接口
 * @author ben
 * @date 2021-08-25 13:30:53 CST
 */
@RestController
@RequestMapping(value="/try1")
@Slf4j
public class Try1Controller {

	@Autowired
	private MongoTemplate mongoTemplate;
	
	// 数据集：sring
	private final static String COLL_SPRING = "spring";
	
	@GetMapping(value="/getDb")
	public String getDb() {
		return mongoTemplate.getDb().getName();
	}
	
	@GetMapping(value="/getColls")
	public Set<String> getColls() {
		return mongoTemplate.getCollectionNames();
	}
	
	/**
	 * 操作数据：使用Document对象+Map，Collection对象的方法
	 * @author ben
	 * @date 2021-08-25 14:57:36 CST
	 * @return
	 */
	@GetMapping(value="/manData")
	public Boolean manData() {
		MongoCollection<Document> coll = mongoTemplate.getCollection(COLL_SPRING);
		
		log.info("开始数量：{}", coll.countDocuments());
		
		// 1、添加
		Document doc = new Document();
		Map<String, Object> map1 = new HashMap<>(8);
		
		// 注意，key是中文
		map1.put("洲", "亚洲");
		map1.put("国家", "中国");
		doc.putAll(map1);
		InsertOneResult ret = coll.insertOne(doc);
		log.info("insertOne ret={}", ret);
		
		map1.clear();
		doc.clear();
		map1.put("洲", "北美洲");
		map1.put("国家", "美国");
		doc.putAll(map1);
		ret = coll.insertOne(doc);
		log.info("insertOne ret={}", ret);

		map1.clear();
		doc.clear();
		map1.put("continent", "欧洲");
		map1.put("country", "德国");
		doc.putAll(map1);
		ret = coll.insertOne(doc);
		log.info("insertOne ret={}", ret);
		
		log.info("添加后 文档总数：{}", coll.countDocuments());
		
		// 2、查找
		log.info("查找所有：");
		FindIterable<Document> find = coll.find();
		find.forEach(fdoc -> {
			log.info("fdoc={}", fdoc);
		});
		
		// 3、修改
		Bson filter = new Document("continent", "欧洲");
		// 不同的建立方式
		Bson update = new Document().append("$set", new Document("country", "法国"));
		Document udoc = coll.findOneAndUpdate(filter, update);
		log.info("更新 返回 udoc={}", udoc);
		
		udoc = coll.find(filter).first();
		log.info("更新 获取 udoc={}", udoc);
		
		// 4、删除
		DeleteResult dret = coll.deleteOne(filter);
		log.info("删除一个 dret={}, count={}", dret, dret.getDeletedCount());
		
		Bson filter2 = new Document();
		DeleteResult dret2 = coll.deleteMany(filter2);
		log.info("删除所有 dret2={}, count={}", dret2, dret2.getDeletedCount());
		
		log.info("最后 文档总数：{}", coll.countDocuments());
		
		return true;
	}
	
	/**
	 * 操作数据：使用实体类，mongoTemplate直接操作
	 * @author ben
	 * @date 2021-08-25 14:57:49 CST
	 * @return
	 */
	@GetMapping(value="/manDataWithEntity")
	public Boolean manDataWithEntity() {
		Date now = new Date();
		
		// 1、添加
		User1 u1 = new User1();
		u1.setName("u1");
		u1.setAge(1);
		u1.setCreateTime(now);
		u1.setUpdateTime(now);
		log.info("insert前 u1={}", u1);
		User1 nu1 = mongoTemplate.insert(u1);
		log.info("insert后 u1={}", u1);
		log.info("insert返回 nu1={}", nu1);
		
		List<User1> ul = new ArrayList<>();
		IntStream.range(0, 5).forEach(i -> {
			User1 mu = new User1();
			mu.setName(String.format("multi-%d", i));
			mu.setAge((i+1) *2);
			mu.setCreateTime(now);
			mu.setUpdateTime(now);
			ul.add(mu);
		});
		log.info("insertAll前 ul={}", ul);
		Collection<User1> retul = mongoTemplate.insertAll(ul);
		log.info("insertAll后 ul={}", ul);
		log.info("insertAll返回 retul={}", retul);
		
		Query qy = new Query();
		long cnt = mongoTemplate.count(qy, User1.class);
		log.info("添加后总数：{}", cnt);
		
		// 2、查找
		// 查找以 multi- 开头的记录数
		qy.addCriteria(Criteria.where("name").regex("^multi-*"));
		log.info("以'multi-'开头的记录数：{}", mongoTemplate.count(qy, User1.class));
		
		// 3、修改
		Update update = new Update();
		final int newAge = 12;
		update.set("age", newAge);
		UpdateResult uret = mongoTemplate.updateMulti(qy, update, User1.class);
		log.info("修改 uret={}", uret);
		
		// 高风险！
		log.info("遍历集合中数据：");
		mongoTemplate.findAll(User1.class).forEach(u -> {
			log.info("u={}", u);
		});
		
		// 4、删除
		Query dqy1 = new Query();
		dqy1.addCriteria(Criteria.where("age").is(newAge));
		DeleteResult dret1 = mongoTemplate.remove(dqy1, User1.class);
		log.info("删除 dret1={}, count={}", dret1, dret1.getDeletedCount());
		
		// 删除所有
		Query dqy2 = new Query();
		DeleteResult dret2 = mongoTemplate.remove(dqy2, User1.class);
		log.info("删除 dret2={}, count={}", dret2, dret2.getDeletedCount());
		
		log.info("结束 记录数：{}", mongoTemplate.count(dqy2, User1.class));
		
		return true;
	}
	
}
